package com.ruoyi.common.utils;

import org.w3c.dom.Attr;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

import javax.imageio.*;
import javax.imageio.metadata.*;
import javax.imageio.stream.*;
import java.awt.*;
import java.awt.image.*;
import java.io.*;
import java.util.*;
import java.awt.geom.AffineTransform;

public class JpgDpiEnhancer {
    // 配置参数
    private static final String INPUT_FOLDER = "C:\\Users\\xinhuiRong\\Desktop\\dpi\\女\\女";    // 输入文件夹
    private static final String OUTPUT_FOLDER = "C:\\Users\\xinhuiRong\\Desktop\\dpi\\女\\output_300dpi"; // 输出文件夹
    private static final int TARGET_DPI = 300;                      // 目标DPI
    private static final float JPEG_QUALITY = 1.0f;                 // 保持原始质量

    public static void main(String[] args) {
        try {
            File inputDir = new File(INPUT_FOLDER);
            File outputDir = new File(OUTPUT_FOLDER);

            // 验证输入目录
            if (!inputDir.exists() || !inputDir.isDirectory()) {
                System.err.println("错误：输入目录不存在 - " + INPUT_FOLDER);
                return;
            }

            // 创建输出目录
            if (!outputDir.exists() && !outputDir.mkdirs()) {
                System.err.println("错误：无法创建输出目录 - " + OUTPUT_FOLDER);
                return;
            }

            // 处理所有JPG文件
            processJpgFiles(inputDir, outputDir);
            System.out.println("\n处理完成！输出目录: " + OUTPUT_FOLDER);

        } catch (Exception e) {
            System.err.println("程序错误: " + e.getMessage());
            e.printStackTrace();
        }
    }

    private static void processJpgFiles(File inputDir, File outputDir) {
        File[] files = inputDir.listFiles((dir, name) -> {
            String lowerName = name.toLowerCase();
            return lowerName.endsWith(".jpg") || lowerName.endsWith(".jpeg");
        });

        if (files == null || files.length == 0) {
            System.out.println("未找到JPG文件");
            return;
        }

        System.out.println("找到 " + files.length + " 个JPG文件，开始处理...");
        for (File jpgFile : files) {
            processSingleJpg(jpgFile, outputDir);
        }
    }

    private static void processSingleJpg(File inputFile, File outputDir) {
        try {
            String fileName = inputFile.getName();
            File outputFile = new File(outputDir, fileName);

            // 读取原始图片和元数据（关键：保留方向信息）
            BufferedImage originalImage = ImageIO.read(inputFile);
            if (originalImage == null) {
                System.err.println("无法读取: " + fileName);
                return;
            }

            // 检查并修复图片方向（解决竖图变横图问题）
            BufferedImage correctedImage = fixImageOrientation(originalImage, inputFile);

            // 获取JPEG写入器
            ImageWriter writer = getJpegWriter();
            if (writer == null) {
                System.err.println("找不到JPEG写入器: " + fileName);
                return;
            }

            try (ImageOutputStream ios = ImageIO.createImageOutputStream(outputFile)) {
                writer.setOutput(ios);
                ImageWriteParam writeParam = writer.getDefaultWriteParam();

                // 关键：保持原始压缩质量（解决图片大小变化问题）
                writeParam.setCompressionMode(ImageWriteParam.MODE_EXPLICIT);
                writeParam.setCompressionQuality(JPEG_QUALITY); // 最高质量

                // 创建元数据并设置DPI
                ImageTypeSpecifier typeSpecifier = ImageTypeSpecifier.createFromRenderedImage(correctedImage);
                IIOMetadata metadata = writer.getDefaultImageMetadata(typeSpecifier, writeParam);
                setDpiMetadata(metadata, TARGET_DPI);

                // 写入图片
                writer.write(null, new IIOImage(correctedImage, null, metadata), writeParam);
            } finally {
                writer.dispose();
                originalImage.flush();
                correctedImage.flush();
            }

            // 验证结果
            if (outputFile.length() == 0) {
                System.err.println("处理失败（空文件）: " + fileName);
            } else {
                System.out.println("成功处理: " + fileName +
                        " (" + correctedImage.getWidth() + "x" + correctedImage.getHeight() + "px, " + TARGET_DPI + "DPI)");
            }

        } catch (Exception e) {
            System.err.println("处理失败 " + inputFile.getName() + ": " + e.getMessage());
        }
    }

    // 【核心修复1】修复图片方向（解决竖图变横图问题）
    private static BufferedImage fixImageOrientation(BufferedImage image, File file) {
        try {
            // 读取EXIF方向信息
            IIOMetadata metadata = ImageIO.read(file).getProperty("metadata") instanceof IIOMetadata ?
                    (IIOMetadata) ImageIO.read(file).getProperty("metadata") : null;

            if (metadata != null) {
                String format = metadata.getNativeMetadataFormatName();
                Node root = metadata.getAsTree(format);

                // 查找方向标签（0x0112）
                Node orientationNode = findNode(root, "orientation");
                if (orientationNode != null) {
                    int orientation = Integer.parseInt(orientationNode.getAttributes().getNamedItem("value").getNodeValue());

                    // 根据方向值旋转/翻转图片
                    AffineTransform transform = new AffineTransform();
                    switch (orientation) {
                        case 2: // 水平翻转
                            transform.scale(-1, 1);
                            transform.translate(-image.getWidth(), 0);
                            break;
                        case 3: // 180度旋转
                            transform.translate(image.getWidth(), image.getHeight());
                            transform.rotate(Math.PI);
                            break;
                        case 4: // 垂直翻转
                            transform.scale(1, -1);
                            transform.translate(0, -image.getHeight());
                            break;
                        case 5: // 顺时针旋转90度并水平翻转
                            transform.rotate(-Math.PI/2);
                            transform.scale(-1, 1);
                            break;
                        case 6: // 顺时针旋转90度
                            transform.rotate(-Math.PI/2);
                            transform.translate(-image.getHeight(), 0);
                            break;
                        case 7: // 顺时针旋转90度并垂直翻转
                            transform.rotate(-Math.PI/2);
                            transform.translate(-image.getHeight(), image.getWidth());
                            transform.scale(1, -1);
                            break;
                        case 8: // 逆时针旋转90度
                            transform.rotate(Math.PI/2);
                            transform.translate(image.getWidth(), 0);
                            break;
                        default: // 正常方向（1）
                            return image;
                    }

                    // 应用变换并返回校正后的图片
                    BufferedImage corrected = new BufferedImage(
                            image.getWidth(), image.getHeight(), BufferedImage.TYPE_INT_RGB);
                    Graphics2D g = corrected.createGraphics();
                    g.setTransform(transform);
                    g.drawImage(image, 0, 0, null);
                    g.dispose();
                    return corrected;
                }
            }
        } catch (Exception e) {
            // 方向处理失败时返回原图
            System.err.println("方向校正失败: " + e.getMessage());
        }
        return image;
    }

    // 【核心修复2】设置DPI元数据（确保DPI生效）
    private static void setDpiMetadata(IIOMetadata metadata, int dpi) throws IIOInvalidTreeException {
        // 计算像素大小（毫米/像素）= 25.4毫米(1英寸) / DPI
        double pixelSize = 25.4 / dpi;

        // 使用标准元数据格式
        String metaFormat = "javax_imageio_1.0";
        Node root = metadata.getAsTree(metaFormat);

        // 设置水平和垂直像素尺寸
        setNodeValue(root, "HorizontalPixelSize", Double.toString(pixelSize));
        setNodeValue(root, "VerticalPixelSize", Double.toString(pixelSize));

        // 合并修改后的元数据
        metadata.mergeTree(metaFormat, root);
    }

    // 辅助方法：查找XML节点
    private static Node findNode(Node root, String nodeName) {
        NodeList nodes = root.getChildNodes();
        for (int i = 0; i < nodes.getLength(); i++) {
            Node node = nodes.item(i);
            if (nodeName.equals(node.getNodeName())) {
                return node;
            }
            Node found = findNode(node, nodeName);
            if (found != null) return found;
        }
        return null;
    }

    // 辅助方法：设置节点值
    private static void setNodeValue(Node root, String nodeName, String value) {
        Node node = findNode(root, nodeName);
        if (node == null) {
            // 创建新节点
            Document doc = root.getOwnerDocument();
            node = doc.createElement(nodeName);
            root.appendChild(node);
        }
        // 设置值属性
        Attr attr = node.getOwnerDocument().createAttribute("value");
        attr.setNodeValue(value);
        node.getAttributes().setNamedItem(attr);
    }

    // 获取JPEG写入器
    private static ImageWriter getJpegWriter() {
        Iterator<ImageWriter> writers = ImageIO.getImageWritersByFormatName("jpeg");
        if (writers.hasNext()) {
            return writers.next();
        }
        return null;
    }
}